package net.dopan.pigframe.core.bean.config;

import com.alibaba.fastjson.parser.ParserConfig;
import net.dopan.pigframe.core.redis.cache.CustomizedRedisCacheManager;
import net.dopan.pigframe.core.redis.serializer.FastJsonRedisSerializer;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheWriter;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import java.time.Duration;


/**
 * @Package: net.dopan.pigframe.core.bean.config
 * @Title: RedisConfig
 * @Description: redis 配置
 * @author: 刘宽
 * @date: 2018/9/6 10:58
 */
@Configuration
@EnableCaching
public class RedisConfig extends CachingConfigurerSupport {

    @Value("${redis.cache.expiration:3600}")
    private Long expiration;

    /*@Bean
    public CacheManager cacheManager(RedisConnectionFactory connectionFactory) {
        RedisCacheWriter writer = RedisCacheWriter.lockingRedisCacheWriter(connectionFactory);
        *//*构造一个RedisCache的配置，比如是否使用前缀，比如Key和Value的序列化机制*//*
        RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
                // 设置缓存有效期
                .entryTtl(Duration.ofSeconds(expiration));
        *//*创建CacheManager，并返回给Spring 容器*//*
        return new CustomizedRedisCacheManager(writer,config);
    }

    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(factory);
        template.setKeySerializer(new StringRedisSerializer());
        template.setValueSerializer(new JdkSerializationRedisSerializer());
        return template;
    }*/

    @Bean
    @Override
    public KeyGenerator keyGenerator() {
        return (target, method, params) -> {
            StringBuilder sb = new StringBuilder();
            sb.append(target.getClass().getName());
            sb.append(method.getName());
            for (Object obj : params) {
                sb.append(obj.toString());
            }
            return sb.toString();
        };
    }

    @Bean
    public CacheManager cacheManager(RedisConnectionFactory connectionFactory) {
        RedisCacheWriter writer = RedisCacheWriter.lockingRedisCacheWriter(connectionFactory);
        ParserConfig.getGlobalInstance().setAutoTypeSupport(true);

        /*SerializationPair用于Java和Redis之间的序列化和反序列化*/
        RedisSerializationContext.SerializationPair valuePair = RedisSerializationContext.SerializationPair
                .fromSerializer(new FastJsonRedisSerializer(Object.class));
        RedisSerializationContext.SerializationPair<String> keyPair = RedisSerializationContext
                .SerializationPair.fromSerializer(new StringRedisSerializer());

        /*构造一个RedisCache的配置，比如是否使用前缀，比如Key和Value的序列化机制*/
        RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
                // 设置缓存有效期
                .entryTtl(Duration.ofSeconds(expiration))
                .serializeValuesWith(valuePair)
                .serializeKeysWith(keyPair);
        /*创建CacheManager，并返回给Spring 容器*/
        return new CustomizedRedisCacheManager(writer,config);
    }

    @Bean
    public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
        RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(connectionFactory);

        FastJsonRedisSerializer<Object> fastJsonRedisSerializer = new FastJsonRedisSerializer(Object.class);
        redisTemplate.setValueSerializer(fastJsonRedisSerializer);
        redisTemplate.setHashValueSerializer(fastJsonRedisSerializer);

        // 设置键（key）的序列化采用StringRedisSerializer。
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashKeySerializer(new StringRedisSerializer());
        redisTemplate.afterPropertiesSet();
        return redisTemplate;
    }
}
